home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
mxcode
/
fmplay11
/
fmplay.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-26
|
5KB
|
202 lines
#include<stdlib.h>
#include<stdio.h>
#include<dos.h>
#include"adlib.h"
#include"fmplay.h"
/**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING***\
* This module MUST be compiled with stack checking OFF in BC 3.0 *
\**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING***/
/* We wish that THIS would turn stack checking off, but it doesn't work */
#pragma -N-
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
#define NMVOICES 11
/* freqTable[60] is the frequency for middle C. 61=c# 62=d &c */
int freqTable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,516,547,580,614,651,
689,730,774,820,869,920,975,1540,1571,1604,1638,1675,1713,1754,1798,1844,1893,
1944,1999,2564,2595,2628,2662,2699,2737,2778,2822,2868,2917,2968,3023,3588,
3619,3652,3686,3723,3761,3802,3846,3892,3941,3992,4047,4612,4643,4676,4710,
4747,4785,4826,4870,4916,4965,5016,5071,5636,5667,5700,5734,5771,5809,5850,
5894,5940,5989,6040,6095,6660,6691,6724,6758,6795,6833,6874,6918,6964,7013,
7064,7119,7684,7715,7748,7782,7819};
/* The frequency table was generated by the following code: */
#if 0
void initFreqTable(void)
{double f,fn;
BYTE b;
int i;
f=16.352;
for (i=12;i<108;i++)
{b=7-((int)(log(6208.43115/f)/0.69314718));
fn=f*(1 << (7-b))/6.0688476;
freqTable[i]=(b << 10)+(int)fn;
f*=1.059463094;
}
}
#endif
void interrupt (*oldHandler)(__CPPARGS)=NULL;
volatile static BYTE *currentSong=NULL,*cp;
volatile static int noteTimer[NMVOICES]={0,0,0,0,0,0,0,0,0,0,0},
pauseTime,tempoDivider,tdc;
volatile int songPlaying=0,interruptCount=0;
int timerDivisor,loop;
int FMSongPlaying(void)
{return songPlaying;
}
void FMPlayNextTick(void)
{int i,j,k,nonePlaying;
if (!songPlaying || --tdc>0) return;
tdc=tempoDivider;
nonePlaying=1;
for (i=0;i<NMVOICES;i++)
{if (noteTimer[i]>0)
{nonePlaying=0;
if (--noteTimer[i]<=0)
FMKeyOff(i);
}
}
if (!currentSong) /* current song goes NULL when the script has run out */
{if (nonePlaying) /* songPlaying goes null when all the notes turn off */
{songPlaying=0;
}
return;
}
if (--pauseTime<=0)
{pauseTime=0;
while (!pauseTime)
{switch (*cp)
{case 0: /* play note */
i=cp[1];
j=cp[2];
k=*((int *)(cp+3));
FMKeyOn(i,freqTable[j]);
noteTimer[i]=k;
cp+=5;
break;
case 2: /* change instrument */
i=cp[1];
j=cp[2];
FMSetVoice(i,(FMInstrument *)(currentSong+2+sizeof(FMInstrument)*j));
cp+=3;
break;
case 3: /* pause */
i=*((int *)(cp+1));
pauseTime=i;
cp+=3;
break;
case 4: /* end of song */
if (!loop)
currentSong=NULL;
else
{pauseTime=loop;
cp=currentSong+(*(currentSong+1))*sizeof(FMInstrument)+2;
}
return;
}
}
}
}
void FMStartSong(BYTE *songData,int speed,int loop1)
{int i;
disable(); /* disable interupts */
tempoDivider=speed;
tdc=0;
currentSong=songData;
songPlaying=1;
pauseTime=0;
cp=currentSong+(*(currentSong+1))*sizeof(FMInstrument)+2;
FMReset(*currentSong);
for (i=0;i<NMVOICES;i++)
noteTimer[i]=0;
loop=loop1;
enable(); /* enable interupts */
}
void FMStopSong(void)
{disable(); /* disable interupts */
currentSong=NULL;
while (songPlaying)
FMPlayNextTick();
enable(); /* enable interupts */
}
BYTE *FMLoadSong(char *name)
{FILE *ifile;
BYTE *rol;
int rolSize;
ifile=fopen(name,"rb");
if (!ifile)
return NULL;
fseek(ifile,0,SEEK_END);
rolSize=ftell(ifile);
fseek(ifile,0,SEEK_SET);
rol=(BYTE *)malloc(sizeof(BYTE)*rolSize);
if (!rol)
{fclose(ifile);
return NULL;
}
if (fread(rol,sizeof(BYTE),rolSize,ifile)!=rolSize)
{fclose(ifile);
return NULL;
}
fclose(ifile);
return rol;
}
void interrupt FMISR(__CPPARGS)
{FMPlayNextTick();
if (++interruptCount>=timerDivisor)
{interruptCount=0;
oldHandler();
}
}
void FMInstallISR(int td)
{unsigned int timerSpeed;
timerDivisor=td;
if (td!=1)
{/* tell the timer to speed up the ticks */
timerSpeed=0x10000L/td;
disable();
outp(0x43, 0x36);
outp(0x40, timerSpeed & 0xff);
outp(0x40, timerSpeed >> 8);
enable();
}
oldHandler = _dos_getvect(0x1c);
_dos_setvect(0x1c, FMISR);
}
void FMRemoveISR(void)
{if (oldHandler)
{_dos_setvect(0x1c, oldHandler);
if (timerDivisor!=1)
{/* return the ticks to normal speed */
disable();
outp(0x43, 0x36);
outp(0x40, 0);
outp(0x40, 0);
enable();
}
}
}